package gui.mainWindow.targetAssignment;

import gui.mainWindow.MainWindow;

import java.util.Observable;
import java.util.Observer;

import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;

import table.models.ParticipantsTableModel;
import tournamentData.EmptyTarget;
import tournamentData.Target;
import tournamentData.TournamentData;
import core.Person;
import dataBase.DbHolder;

public class TargetAssignmentController implements Observer {
	MainWindow window;

	public TargetAssignmentController(MainWindow mainWindow) {
		this.window = mainWindow;
		TournamentData.getInstance().addObserver(this);
		TournamentData.getInstance().getTargetAssignment().addObserver(this);
	}

	public void incrementNumberOfTargets() {
		TournamentData.getInstance().setNumberOfTargets(TournamentData.getInstance().getNumberOfTargets() + 1);
	}

	public void decrementNumberOfTargets() {
		TournamentData.getInstance().setNumberOfTargets(TournamentData.getInstance().getNumberOfTargets() - 1);
	}

	public void incrementPlayersPerTarget() {
		TournamentData.getInstance().setPlayersPerTarget(TournamentData.getInstance().getPlayersPerTarget() + 1);
	}

	public void decrementPlayersPerTarget() {
		TournamentData.getInstance().setPlayersPerTarget(TournamentData.getInstance().getPlayersPerTarget() - 1);
	}

	public void setTargetAssignmentNumbers() {
		this.window.getNumberOfTargetsLabel().setText(new Integer(TournamentData.getInstance().getNumberOfTargets()).toString());
		this.window.getPlayersPerTargetLabel().setText(new Integer(TournamentData.getInstance().getPlayersPerTarget()).toString());
	}

	public void setTargetNumberDropDown() {
		int indexToSetSelected = 0;
		// already has values stored
		if (this.window.getTargetNumberDropDown().getItemCount() > 0) {
			indexToSetSelected = this.window.getTargetNumberDropDown().getSelectedIndex();
		}
		int numberOfTargets = TournamentData.getInstance().getNumberOfTargets();
		ComboBoxModel targetNumberDropDownModel = new DefaultComboBoxModel();
		this.window.getTargetNumberDropDown().setModel(targetNumberDropDownModel);
		for (int i = 1; i <= numberOfTargets; i++) {
			this.window.getTargetNumberDropDown().addItem(i);
		}
		this.window.getTargetNumberDropDown().setSelectedIndex(indexToSetSelected);
	}

	public void setTargetCharDropDown() {
		// int indexToSetSelected = 0;
		// // already has values stored
		// if (this.window.getTargetCharDropDown().getItemCount() > 0) {
		// indexToSetSelected =
		// this.window.getTargetCharDropDown().getSelectedIndex();
		// }
		int playersPerTarget = TournamentData.getInstance().getPlayersPerTarget();
		ComboBoxModel targetCharDropDownModel = new DefaultComboBoxModel();
		this.window.getTargetCharDropDown().setModel(targetCharDropDownModel);
		char toAssign = 'A';
		for (int i = 1; i <= playersPerTarget; i++) {
			this.window.getTargetCharDropDown().addItem(toAssign);
			toAssign++;
		}
		// this.window.getTargetCharDropDown().setSelectedIndex(indexToSetSelected);
	}

	public void buildTargetAssignmentTable() {
		if (TournamentData.getInstance().getAllParticipants().length > 0) {
			ParticipantsTableModel model = (ParticipantsTableModel) this.window.getTargetAssignmentTable().getModel();
			int selectedRow = this.window.getTargetAssignmentTable().getSelectedRow();
			try {
				model.getSemaphore().acquire();
				model.removeData();
				for (int i = 0; i < TournamentData.getInstance().getAllParticipants().length; i++) {
					int playerID = TournamentData.getInstance().getAllParticipants() [i];
					Person toAdd = DbHolder.getInstance().getArcherData().getById(playerID);
					Target target = TournamentData.getInstance().getTargetAssignment().getTargetForPlayer(playerID);
					if (target == null) {
						target = new EmptyTarget(0, 'A');
					}

					Object [] rowToAdd = new Object [] { playerID, target, toAdd.getName(), toAdd.getSurName(), toAdd.getClub(), toAdd.getBowCathegory(), toAdd.getAgeClass(), toAdd.getGender() };
					model.addRow(rowToAdd);
				}
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			} finally {
				model.getSemaphore().release();
			}

			if (TournamentData.getInstance().getAllParticipants().length > 0) {
				try {
					this.window.getTargetAssignmentTable().setRowSelectionInterval(selectedRow, selectedRow);
				} catch (IllegalArgumentException e) {
					this.window.getTargetAssignmentTable().setRowSelectionInterval(0, 0);
				}
			}
		}
	}

	@Override
	public void update(Observable arg0, Object arg1) {
		this.window.getTargetAssignmentTable().repaint();
		this.setTargetAssignmentNumbers();
		this.setTargetNumberDropDown();
		this.setTargetCharDropDown();
		this.buildTargetAssignmentTable();
		this.markNextUnassignedPlayer();
		this.setNexUnassignedTargetSelected();
		this.window.getTargetAssignmentTable().repaint();
	}

	public void assignPlayer() {
		int selectedTargetNumber = this.getSelectedTargetNumber();
		char selectedTargetChar = this.getSelectedTargetChar();
		int playerID = Integer.parseInt(this.window.getTargetAssignmentTable().getValueAt(this.window.getTargetAssignmentTable().getSelectedRow(), 0).toString());
		TournamentData.getInstance().getTargetAssignment().assignTarget(playerID, new Target(selectedTargetNumber, selectedTargetChar));
		this.window.getTargetAssignmentTable().repaint();
	}

	public void synchDropDownsWithTable() {
		if (this.window.getTargetAssignmentTable().getValueAt(this.window.getTargetAssignmentTable().getSelectedRow(), 0) != null) {
			int playerID = Integer.parseInt(this.window.getTargetAssignmentTable().getValueAt(this.window.getTargetAssignmentTable().getSelectedRow(), 0).toString());
			if (!this.window.getTargetAssignmentTable().getValueAt(this.window.getTargetAssignmentTable().getSelectedRow(), 1).toString().equals("")) {
				Target assigned = TournamentData.getInstance().getTargetAssignment().getTargetForPlayer(playerID);
				this.window.getTargetNumberDropDown().setSelectedItem(assigned.getNumber());
				this.window.getTargetCharDropDown().setSelectedItem(assigned.getCharacter());
			}
		}
	}

	public void markNextUnassignedPlayer() throws IndexOutOfBoundsException {
		if (this.hasUnassignedPlayers()) {
			if (TournamentData.getInstance().getAllParticipants().length > 0) {
				int selectedRow = this.window.getTargetAssignmentTable().getSelectedRow();

				for (int i = selectedRow; i < this.window.getTargetAssignmentTable().getRowCount(); i++) {
					if (this.window.getTargetAssignmentTable().getValueAt(i, 1).toString().equals("")) {
						this.window.getTargetAssignmentTable().setRowSelectionInterval(i, i);
						break;
					}
				}
			}
		}
	}

	private boolean hasUnassignedPlayers() {
		for (int i = 0; i < this.window.getTargetAssignmentTable().getModel().getRowCount(); i++) {
			if ((this.window.getTargetAssignmentTable().getModel().getValueAt(i, 1) == null) || this.window.getTargetAssignmentTable().getModel().getValueAt(i, 1).equals("")) {
				return true;
			}
		}
		return false;
	}

	public void removeSelectedAssignment() {
		int selectedTargetNumber = this.getSelectedTargetNumber();
		char selectedTargetChar = this.getSelectedTargetChar();
		TournamentData.getInstance().getTargetAssignment().removeAssignmentForTarget(new Target(selectedTargetNumber, selectedTargetChar));
		this.window.getTargetAssignmentTable().repaint();
	}

	public int getSelectedTargetNumber() {
		return Integer.parseInt(this.window.getTargetNumberDropDown().getSelectedItem().toString());
	}

	public char getSelectedTargetChar() {
		return this.window.getTargetCharDropDown().getSelectedItem().toString().charAt(0);
	}

	public void setNexUnassignedTargetSelected() {
		boolean stopSearching = false;
		int targetNumberIndex = this.window.getTargetNumberDropDown().getSelectedIndex();
		int targetCharIndex = this.window.getTargetCharDropDown().getSelectedIndex();

		for (targetNumberIndex = this.window.getTargetNumberDropDown().getSelectedIndex(); targetNumberIndex < this.window.getTargetNumberDropDown().getItemCount(); targetNumberIndex++) {
			for (targetCharIndex = this.window.getTargetCharDropDown().getSelectedIndex(); targetCharIndex < this.window.getTargetCharDropDown().getItemCount(); targetCharIndex++) {
				// System.out.println(targetNumberIndex + " " +
				// targetCharIndex);
				int targetNumber = Integer.parseInt(this.window.getTargetNumberDropDown().getItemAt(targetNumberIndex).toString());
				char targetChar = this.window.getTargetCharDropDown().getItemAt(targetCharIndex).toString().charAt(0);
				if (!TournamentData.getInstance().getTargetAssignment().hasPlayerAssigned(new Target(targetNumber, targetChar))) {
					// System.out.println("next target: " + targetNumber +
					// targetChar);
					stopSearching = true;
					break;
				}
			}
			if (stopSearching) {
				break;
			}
		}
		try {
			this.window.getTargetNumberDropDown().setSelectedIndex(targetNumberIndex);
		} catch (Exception e) {
			this.window.getTargetNumberDropDown().setSelectedIndex(0);
		}
		try {
			this.window.getTargetCharDropDown().setSelectedIndex(targetCharIndex);
		} catch (Exception e) {
			this.window.getTargetCharDropDown().setSelectedIndex(0);
		}
	}

	public void resetAllAssignments() {
		TournamentData.getInstance().getTargetAssignment().resetAllAssignments();
	}
}
